package com.knife.file.domain.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.knife.common.constants.BaseConstants;
import com.knife.file.domain.entity.KnifeFileInfo;
import com.knife.file.domain.entity.KnifeStorageConfig;
import com.knife.file.infra.constants.FileConstant;
import com.knife.file.infra.mapper.KnifeFileInfoMapper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.InputStream;
import java.util.List;
import java.util.UUID;

/**
 * 文件上传业务操作，与用于与支持的文件上传下载解耦
 *
 * @author： 76875
 * @date： 2022/4/6 星期三 18:55
 * @description：
 * @modifiedBy：
 * @version: 1.0
 */
public class KnifeStoreService {
    private KnifeFileService knifeFileService;
    private KnifeStorageConfig knifeStorageConfig;
    private KnifeFileInfoMapper knifeFileInfoMapper;

    public KnifeStoreService(KnifeFileService knifeFileService, KnifeStorageConfig knifeStorageConfig, KnifeFileInfoMapper knifeFileInfoMapper) {
        this.knifeFileService = knifeFileService;
        this.knifeStorageConfig = knifeStorageConfig;
        this.knifeFileInfoMapper = knifeFileInfoMapper;
    }

    public KnifeFileService getKnifeFileService() {
        return knifeFileService;
    }

    public KnifeStorageConfig getKnifeStorageConfig() {
        return knifeStorageConfig;
    }

    public KnifeFileInfoMapper getKnifeFileInfoMapper() {
        return knifeFileInfoMapper;
    }

    /**
     * 通过文件上传
     *
     * @param fileInfo 文件信息
     * @param filePath     文件
     * @return 文件信息
     */
    public KnifeFileInfo uploadFile(KnifeFileInfo fileInfo, String filePath) {
        fileInfo.setSourceType(knifeStorageConfig.getStorageType().toString());
        fileInfo.initFileKey(buildFileName(fileInfo.getFileName()));
        String fileUrl = null;
        // 如果md5值在系统中有数据了，根据存储配置则attribute1来判断是否还需要重复上传文件至服务器，为Y表示需要重复上传
        if (StringUtils.isNotEmpty(fileInfo.getMd5()) && !BaseConstants.Flag.Y.equals(knifeStorageConfig.getAttribute1())) {
            // 获取判断是否已有md5在了
            QueryWrapper<KnifeFileInfo> qw = new QueryWrapper<>();
            qw.eq(KnifeFileInfo.FIELD_MD5, fileInfo.getMd5());
            List<KnifeFileInfo> dbFileInfoList = knifeFileInfoMapper.selectList(qw);
            if (CollectionUtils.isNotEmpty(dbFileInfoList)) {
                fileUrl = dbFileInfoList.get(0).getFileUrl();
            }
        }
        if (StringUtils.isEmpty(fileUrl)) {
            fileUrl = knifeFileService.upload(fileInfo, filePath);
        }
        fileInfo.setFileUrl(fileUrl);
        knifeFileInfoMapper.insert(fileInfo);
        return fileInfo;
    }


    /**
     * 通过输入流文件上传
     *
     * @param fileInfo    文件信息
     * @param inputStream 输入流
     * @return 文件信息
     */
    public KnifeFileInfo uploadFile(KnifeFileInfo fileInfo, InputStream inputStream) {
        fileInfo.setSourceType(knifeStorageConfig.getStorageType().toString());
        fileInfo.initFileKey(buildFileName(fileInfo.getFileName()));
        String fileUrl = null;
        // 如果md5值在系统中有数据了，根据存储配置则attribute1来判断是否还需要重复上传文件至服务器，为Y表示需要重复上传
        if (StringUtils.isNotEmpty(fileInfo.getMd5()) && !BaseConstants.Flag.Y.equals(knifeStorageConfig.getAttribute1())) {
            // 获取判断是否已有md5在了
            QueryWrapper<KnifeFileInfo> qw = new QueryWrapper<>();
            qw.eq(KnifeFileInfo.FIELD_MD5, fileInfo.getMd5());
            List<KnifeFileInfo> dbFileInfoList = knifeFileInfoMapper.selectList(qw);
            if (CollectionUtils.isNotEmpty(dbFileInfoList)) {
                fileUrl = dbFileInfoList.get(0).getFileUrl();
            }
        }
        if (StringUtils.isEmpty(fileUrl)) {
            fileUrl = knifeFileService.upload(fileInfo, inputStream);
        }
        fileInfo.setFileUrl(fileUrl);
        knifeFileInfoMapper.insert(fileInfo);
        return fileInfo;
    }


    /**
     * 构建文件名
     *
     * @param fileName 文件名
     * @return 带前缀的文件名
     */
    private String buildFileName(String fileName) {
        String prefixStrategy = StringUtils.isBlank(knifeStorageConfig.getPrefixStrategy()) ? FileConstant.KnifeFileConstant.PrefixStrategy.UUID : knifeStorageConfig.getPrefixStrategy();
        // 根据指定策略生成带前缀的文件名
        switch (prefixStrategy) {
            case FileConstant.KnifeFileConstant.PrefixStrategy.NONE:
                return fileName;
            case FileConstant.KnifeFileConstant.PrefixStrategy.FOLDER:
                return generateUUID() + FileConstant.KnifeFileConstant.DIRECTORY_SEPARATOR + fileName;
            case FileConstant.KnifeFileConstant.PrefixStrategy.UUID:
            default:
                return generateUUID() + FileConstant.KnifeFileConstant.DEFAULT_SPLIT_SYMBOL + fileName;
        }
    }

    private String generateUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
}
